﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;
using BoneSystem.Extensions.Annotations;
using BoneSystem.Extensions.Components;

namespace BoneSystem.Extensions.Grid
{
    public class GridLayout<T, TPropertie>: Component
    {
        public GridLayout(HtmlHelper<T> htmlHelper, Expression<Func<T, TPropertie>> expression)
        {
            HtmlHelper = htmlHelper;
            ExpressionData = expression;
            Columns = new List<GridColumnSettins>();
            GridHeader = new List<AngularTag>();
            GridBody = new List<AngularTag>();
            GridFooder = new List<AngularTag>();
        }

        public IList<GridColumnSettins> Columns { get; set; }

        public IList<AngularTag> GridHeader { get; set; }
        public IList<AngularTag> GridBody { get; set; }
        public IList<AngularTag> GridFooder { get; set; }
        public new GridSettings Settings { get; set; }
        private HtmlHelper<T> HtmlHelper { get; set; }
        private Expression<Func<T, TPropertie>> ExpressionData { get; set; }

        public override MvcHtmlString GetHtmlString()
        {
            var model = ModelMetadata.FromLambdaExpression(ExpressionData, HtmlHelper.ViewData);

            if (model.ModelType != null && model.ModelType.IsGenericType)
            {
                LerAttributes(model.ModelType.GenericTypeArguments[0]);

            }
            else
            {
                LerAttributes(model.ModelType);
            }

            MontaHeader();

            MontaBody();

            MontaFooder();

            return new MvcHtmlString(GetTag().ToString(TagRenderMode.Normal));
        }

        internal override AngularTag GetTag()
        {
            var dataObject = Settings.DataObject.Replace("$", "");
            var dataValue = dataObject + "Value";

            var tagTable = new AngularTag("table");
            var tagHeader = new AngularTag("thead");
            var tagBody = new AngularTag("tbody");

            // Linhas da tabela
            var tagRowHeader = new AngularTag("tr");
            var tagRowBody = new AngularTag("tr");
            var tagRowFooder = new AngularTag("tr");



            // Atributos da tabela.
            tagTable.Attributes["ng-table"] = "tableParams";

            // Atributo class
            if (string.IsNullOrEmpty(Settings.Class))
            {
                tagTable.Attributes["class"] = "table table-striped";
            }
            else
            {
                tagTable.Attributes["class"] = Settings.Class;
            }

            // Aciona o ng-repeat dentro da tagRowBody
            tagRowBody.Attributes["ng-repeat"] = Settings.DataObject.Replace("$", "") + "Value in " + Settings.DataObject;

            //foreach (var angularTag in GridHeader)
            //{
            //    tagRowHeader.InnerHtml += angularTag.ToString(TagRenderMode.Normal);
            //}

            foreach (var angularTag in GridBody)
            {
                tagRowBody.InnerHtml += angularTag.ToString(TagRenderMode.Normal);
            }

            //foreach (var angularTag in GridFooder)
            //{
            //    tagRowFooder.InnerHtml += angularTag.ToString(TagRenderMode.Normal);
            //}

            //tagHeader.InnerHtml = tagRowHeader.ToString(TagRenderMode.Normal);
            //tagBody.InnerHtml = tagRowBody.ToString(TagRenderMode.Normal) + tagRowFooder.ToString(TagRenderMode.Normal);
            //tagTable.InnerHtml = tagHeader.ToString(TagRenderMode.Normal) + tagBody.ToString(TagRenderMode.Normal);
            
            //HtmlHelper.ViewContext.Writer.WriteLine(ret);
            tagRowBody.Attributes["ng-click"] = dataValue + ".$selected = !" + dataValue + ".$selected; " + dataObject + "ChangeSelection(" + dataValue + ")";

            tagRowBody.Attributes["ng-class"] = "{ 'info': " + dataValue + ".Id == selectedIdentifer }";

            tagTable.InnerHtml = tagRowBody.ToString();
            return tagTable;
        }

        
        private void MontaFooder()
        {

        }
        private void MontaHeader()
        {
            foreach (var gridColumn in Columns.OrderBy(x => x.Order))
            {
                var tag = new AngularTag("th");
                tag.Attributes["style"] = "width: " + gridColumn.Width.ToString(CultureInfo.InvariantCulture) + "px;";
                //tag.Attributes["data-title"] = "'"+gridColumn.DisplayName +"'";
                tag.InnerHtml = gridColumn.DisplayName;
                GridHeader.Add(tag);
            }
        }

        private void MontaBody()
        {
            var dataObject = Settings.DataObject.Replace("$", "");
            var dataValue = dataObject + "Value";
            foreach (var gridColumn in Columns.OrderBy(x => x.Order))
            {
                var field = dataValue + "." + gridColumn.FieldName;
                var tag = new AngularTag("td");
                tag.Attributes["style"] = "width: " + gridColumn.Width.ToString(CultureInfo.InvariantCulture) + "px";
                tag.Attributes["data-title"] ="'"+ gridColumn.DisplayName + "'";

                if (gridColumn.Sortable)
                {
                    tag.Attributes["sortable"] = "'" + gridColumn.FieldName + "'";
                }
                if (gridColumn.Filter)
                {
                    tag.Attributes["filter"] = "{ '" + gridColumn.FieldName + "': 'text' }";
                }

                tag.InnerHtml = "{{" + field + "}}";
                GridBody.Add(tag);
            }
        }

        private void LerAttributes(Type type)
        {
            var gridAttribute = type.GetCustomAttributes(typeof(GridAttribute), true);
            if (!gridAttribute.Any())
            {
                throw new Exception("A classe " + type.FullName + "' não é um tipo grid");
            }
            Settings.DataObject = ((GridAttribute)gridAttribute[0]).DataObject;
            var fields = type.GetProperties();
            foreach (var fieldInfo in fields)
            {
                foreach (GridColumnAttribute customAttribute in fieldInfo.GetCustomAttributes(typeof(GridColumnAttribute), true))
                {
                    var col = new GridColumnSettins();

                    col.DisplayName = customAttribute.DisplayName;
                    col.FieldName = customAttribute.FieldName;
                    col.TableColumnName = customAttribute.TableColumnName;
                    col.Order = customAttribute.Order;
                    col.Width = customAttribute.Width;
                    col.Sortable = customAttribute.Sortable;
                    col.Filter = customAttribute.Filter;

                    if (string.IsNullOrEmpty(col.FieldName))
                    {
                        col.FieldName = fieldInfo.Name;
                    }

                    Columns.Add(col);
                }
            }
        }
    }
}
